﻿using Antlr4.Runtime.Misc;
using System;
using System.Collections.Generic;
using System.Text;
using TT.Compiler.Node;

namespace TT.Compiler.Define
{



    public class DefineVistor : ttparser.ttlangBaseVisitor<IDocNode>
    {

        Stack<string> namespaces = new Stack<string>();

        Stack<TypeDefine> curTypes = new Stack<TypeDefine>();
        public string GetCurNameSpace()
        {
            var arr = namespaces.ToArray();
            StringBuilder sb = new StringBuilder();
            for (var i = 0; i < arr.Length; i++)
            {
                sb.Append(arr[0]);
                if (i != arr.Length - 1)
                {
                    sb.Append(".");
                }
            }
            return sb.ToString();
        }
        public TypeDefine GetCurType()
        {
            if (curTypes.Count == 0)
                return null;
            return curTypes.Peek();
        }
        public string GetCurType_FullName()
        {
            if (curTypes.Count == 0)
                return TypeDefine.glabolDefineName;
            return curTypes.Peek().FullName;
        }
        public DefineVistor()
        {

        }
        public override IDocNode VisitRoot([NotNull] ttparser.ttlangParser.RootContext context)
        {
            var doc = TypeDefine.CreateDocument(context);
            foreach (var c in context.children)
            {
                var node = Visit(c);
                if (node is FuncDefine)
                {
                    doc.AddFunc(node as FuncDefine);
                }
                else if (node is FieldDefine)
                {
                    doc.AddField(node as FieldDefine);
                }
                if (node is TypeDefine)
                {
                    doc.AddOtherType(node as TypeDefine);
                }
            }
            //return base.VisitRoot(context);
            return doc;
        }
        public override IDocNode VisitDoc_enum_def([NotNull] ttparser.ttlangParser.Doc_enum_defContext context)
        {
            var _namespace = GetCurNameSpace();
            var name = NodeHelper.ConvID(context.ID());
            TypeDefine enumdef = new TypeDefine(context, TypeDefineType.Enum, _namespace, name);

            var mod = NodeHelper.ConvModifier(context.modifier());
            if (mod != Modifier.None && mod != Modifier.Export)
                throw new Exception("error enum modifier");
            enumdef.Modifier = mod;

            enumdef.BaseTypeRef = "int32";// IntType.UInt32;//这个还没有定义

            UInt64 startvalue = 0;
            foreach (var item in context.enum_item())
            {
                var key = NodeHelper.ConvID(item.ID());
                var v = startvalue;
                NodeHelper.TryConvInt(item.number(), ref v);

                var field = new FieldDefine(item, enumdef.FullName, key);
                field.DefaultValue = v;
                enumdef.AddField(field);
                startvalue = v + 1;
            }

            return enumdef;
        }
        public override IDocNode VisitDoc_method_def([NotNull] ttparser.ttlangParser.Doc_method_defContext context)
        {
            var name = NodeHelper.ConvID(context.ID());
            var parentName = GetCurType_FullName();
            var func = new FuncDefine(context, parentName, name);

            var parent = GetCurType();

            if (parent!=null)
                parent.AddFunc(func);

            return func;
        }

    }
}
